
using Nop.Core;
using Nop.Core.Caching;
using Nop.Core.Data;
using Nop.Core.Domain.Customers;
using Nop.Services.Events;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Nop.Services.Customers
{
    /// <summary>
    /// Person service
    /// </summary>
    public partial class PersonService : IPersonService
    {
        #region Constants

        /// <summary>
        /// Key for caching
        /// </summary>
        private const string PERSONS_ALL_KEY = "Nop.person.all";
        /// <summary>
        /// Key for caching
        /// </summary>
        /// <remarks>
        /// {0} : person ID
        /// </remarks>
        private const string PERSON_BY_ID_KEY = "Nop.person.id-{0}";
        /// <summary>
        /// Key pattern to clear cache
        /// </summary>
        private const string PERSONS_PATTERN_KEY = "Nop.person.";
        #endregion

        #region Fields
        private readonly IRepository<Person> _personRepository;
        private readonly IEventPublisher _eventPublisher;
        private readonly ICacheManager _cacheManager;
        #endregion

        #region Ctor

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="cacheManager">Cache manager</param>
        /// <param name="personRepository">Person repository</param>
        /// <param name="eventPublisher">Event published</param>
        public PersonService(ICacheManager cacheManager,
            IRepository<Person> personRepository,
            IEventPublisher eventPublisher)
        {
            this._cacheManager = cacheManager;
            this._personRepository = personRepository;
            this._eventPublisher = eventPublisher;
        }

        #endregion

        #region Methods

        /// <summary>
        /// Gets all Persons
        /// </summary>
        /// <returns>Persons</returns>
        public virtual IList<Person> GetAllPersons()
        {
            string key = PERSONS_ALL_KEY;
            return _cacheManager.Get(key, () =>
            {
                var query = from a in _personRepository.Table
                            orderby a.Id
                            select a;
                return query.ToList();
            });
        }

        public virtual IPagedList<Person> GetPersons(
            string name = null,
            int departId = 0,
            int gwxzId = 0,
            int natureId = 0,
            string sorter = "",
            int pageIndex = 0,
            int pageSize = int.MaxValue)
        {
            var query = _personRepository.Table.Where(c => !c.Deleted);
            if (!string.IsNullOrEmpty(name))
                query = query.Where(m => m.Name.Contains(name));
            query = query.Where(m => 
            (departId == 0 || m.DepartmentId == departId)
            && (gwxzId == 0 || m.GWXZ == gwxzId)
            && (natureId == 0 || m.Nature == natureId));
            switch (sorter)
            {
                default:
                    query = query.OrderBy(c => c.Name);
                    break;
            }
            var persons = new PagedList<Person>(query, pageIndex, pageSize);
            return persons;
        }

        public virtual IList<Person> GetPersonsByIds(int[] personIds)
        {
            if (personIds == null || personIds.Length == 0)
                return new List<Person>();

            var query = from c in _personRepository.Table
                        where personIds.Contains(c.Id) && !c.Deleted
                        select c;
            var projects = query.ToList();
            return projects;
        }

        /// <summary>
        /// Gets a Person 
        /// </summary>
        /// <param name="personId">Person identifier</param>
        /// <returns>Person</returns>
        public virtual Person GetPersonById(int personId)
        {
            if (personId == 0)
                return null;

            string key = string.Format(PERSON_BY_ID_KEY, personId);
            return _cacheManager.Get(key, () => _personRepository.GetById(personId));
        }

        /// <summary>
        /// Inserts a Person
        /// </summary>
        /// <param name="person">Person</param>
        public virtual void InsertPerson(Person person)
        {
            if (person == null)
                throw new ArgumentNullException("person");

            _personRepository.Insert(person);

            _cacheManager.RemoveByPattern(PERSONS_PATTERN_KEY);

            //event notification
            _eventPublisher.EntityInserted(person);
        }

        /// <summary>
        /// Updates the Person
        /// </summary>
        /// <param name="person">Person</param>
        public virtual void UpdatePerson(Person person)
        {
            if (person == null)
                throw new ArgumentNullException("person");

            _personRepository.Update(person);

            _cacheManager.RemoveByPattern(PERSONS_PATTERN_KEY);

            //event notification
            _eventPublisher.EntityUpdated(person);
        }

        /// <summary>
        /// Deletes a Person
        /// </summary>
        /// <param name="person">Person</param>
        public virtual void DeletePerson(Person person)
        {
            if (person == null)
                throw new ArgumentNullException("person");

            _personRepository.Delete(person);

            _cacheManager.RemoveByPattern(PERSONS_PATTERN_KEY);

            //event notification
            _eventPublisher.EntityDeleted(person);
        }

        #endregion
    }
}
